from utils import *
from adbutils import AdbClient
import aircv
import numpy as np
import time


def log(msg):
    # 打出微秒级时间字符串，如：2023-01-01 00:00:00.000000
    time_str = (
        time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        + "."
        + str(time.time() % 1)[2:8]
    )
    print(f"{time_str} {msg}")


@singleton
class ADBEnv:
    def __init__(self):
        self.client = AdbClient(host="127.0.0.1", port=5037)
        self.device = None
        self.image_cache = {}
        self.ss = None
        self.ss_time = None

    def connect(self, deviceName):
        log(f"connect:{deviceName}")
        if self.device is None:
            self.device = self.client.device(deviceName)

    def disconnect(self):
        if self.device is not None:
            self.device = None

    def is_connected(self):
        if self.device is None:
            return False
        try:
            result = self.device.shell("echo ok")
        except Exception:
            return False
        return result == "ok"

    def devices(self) -> list[str]:
        return [device.serial for device in self.client.device_list()]

    def start_record(self):
        log(f"start record")
        self.device.start_recording("record.mp4")

    def stop_record(self):
        log(f"finish record")
        self.device.stop_recording()

    def pull(self, remote, local):
        log(f"pull:{remote} {local}")
        self.device.sync.pull(remote, local)

    def swipe(self, x1, y1, x2, y2, duration: float = 1, delay: float = 1):
        log(f"swipe:{x1} {y1} {x2} {y2} {duration}")
        self.device.swipe(x1, y1, x2, y2, duration)
        self.ss = None
        time.sleep(delay)

    def input_tap(self, x, y, delay: float = 1.5):
        log(f"input_tap:{x} {y}")
        self.device.shell(f"input tap {int(x)} {int(y)}")
        self.ss = None
        time.sleep(delay)

    def save_screen_shot(self):
        self.device.screenshot().save("images/screenshot.png")

    def screen_shot(self):
        if self.ss is None or time.time() - self.ss_time > 5:
            log("screen_shot!")
            self.ss = self.device.screenshot()
            self.ss.save("ss.png")
            self.ss_time = time.time()
        return np.array(self.ss)

    def flush_images(self):
        self.image_cache = {}

    def get_image(self, image_name):
        if image_name not in self.image_cache:
            self.image_cache[image_name] = aircv.imread(f"images/{image_name}")
        return self.image_cache[image_name]

    def find_all(self, template, threshold=0.9):
        log(f"find_all:{template} {threshold}")
        results = aircv.find_all_template(
            self.screen_shot(), self.get_image(template), threshold=threshold
        )
        if results:
            log("find_all: ok")
            return [result["result"] for result in results]
        log("find_all: no")
        return []

    def exists_without(self, template, without, threshold=0.9):
        while self.exists(without, threshold=threshold):
            self.click_buttons([without], threshold=threshold)
        return self.exists(template, threshold=threshold)

    def exists(self, template, threshold=0.9):
        log(f"exists:{template} {threshold}")
        result = aircv.find_template(
            self.screen_shot(), self.get_image(template), threshold=threshold
        )
        log(f"exists:{template} {result is not None}")
        return result is not None

    def click_outside(self):
        log(f"click_outside")
        self.input_tap(550, 150)

    def click_buttons(self, buttons, threshold=0.9):
        log(f"click_buttons:{buttons} {threshold}")
        for button in buttons:
            result = aircv.find_template(
                self.screen_shot(), self.get_image(button), threshold=threshold
            )
            if result:
                log(f"click_buttons: {button}")
                x, y = result["result"]
                self.input_tap(x, y)
                return True
        return False

    def click_buttons_utils_exist(self, buttons, utilsExist, threshold=0.9):
        log(f"click_buttons:{buttons} {threshold}")
        for _ in range(5):
            if aircv.find_template(
                self.screen_shot(), self.get_image(utilsExist), threshold=threshold
            ):
                log(f"exist: {utilsExist}")
                return True
            for button in buttons:
                result = aircv.find_template(
                    self.screen_shot(), self.get_image(button), threshold=threshold
                )
                if result:
                    log(f"click_buttons: {button}")
                    x, y = result["result"]
                    self.input_tap(x, y)
        return False
